package pms.dao;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import pms.dto.RennenRennlaeuferDTO;
import pms.om.Rennen;
import pms.om.Rennlaeufer;

public class RennenDao extends HibernateDaoSupport {
	private RennstatistikDao rennstatistikDao;
	private RennlaeuferDao rennlaeuferDao;
	private SaisonDao saisonDao;
	
	public void setRennstatistikDao(RennstatistikDao rennstatistikDao) {
		this.rennstatistikDao = rennstatistikDao;
	}

	public void setRennlaeuferDao(RennlaeuferDao rennlaeuferDao) {
		this.rennlaeuferDao = rennlaeuferDao;
	}

	public void setSaisonDao(SaisonDao saisonDao) {
		this.saisonDao = saisonDao;
	}

	public Rennen findById(int id) {
		HibernateTemplate template = getHibernateTemplate();
		return (Rennen) template.get(Rennen.class, id);
	}
	
	
	@SuppressWarnings("unchecked")
	public List<Rennen> findAll() {
		HibernateTemplate template = getHibernateTemplate();
		return template.loadAll(Rennen.class);
	}

	/**
	 * <p>returns all Fahrt objects as RennenRennlaeuferDTO objects.</p>
	 * <p>In order to access lazy loaded properties of those, a HibernateCallback is used.</p>
	 * @return A sorted set of RennenRennlaeuferDTO objects
	 * @see http://static.springframework.org/spring/docs/2.5.x/reference/orm.html#orm-hibernate-template
	 */
	@SuppressWarnings("unchecked")
	public Set<RennenRennlaeuferDTO> findAllDTO() {
		HibernateTemplate template = getHibernateTemplate();
		return (Set<RennenRennlaeuferDTO>) template.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(Rennen.class);
				List<Rennen> alleRennen = criteria.list();
				return createDtoSet(alleRennen);
			}
		});
	}
	
//	@SuppressWarnings("unchecked")
//	public List<SaisonRennenLaeuferDTO> findAllVoll() {
//		HibernateTemplate template = getHibernateTemplate();
//		return (List<SaisonRennenLaeuferDTO>) template.execute(new HibernateCallback() {
//			@Override
//			public Object doInHibernate(Session session) throws HibernateException, SQLException {
//				Criteria criteria = session.createCriteria(Rennen.class);
//				List<Rennen> alleRennen = criteria.list();
//				List<SaisonRennenLaeuferDTO> liste = new LinkedList<SaisonRennenLaeuferDTO>();
//				for (Rennen f : alleRennen) {
//					Set<Rennlaeufer> laeufer = f.getRennlaeufer();
//					for (Rennlaeufer p : laeufer) {
//					SaisonRennenLaeuferDTO srlDto = new SaisonRennenLaeuferDTO(f, p);
//						liste.add(srlDto);
//					}
//				}
//				return liste;
//			}
//});
//}

	/**
	 * Private utility function
	 * @param rennen a List of persistent Rennen objects
	 * @return a Set of RennenRennlaeuferDTO objects
	 */
	private Set<RennenRennlaeuferDTO> createDtoSet(List<Rennen> rennen) {
		Set<RennenRennlaeuferDTO> results = new TreeSet<RennenRennlaeuferDTO>();
		for (Rennen r : rennen) {
			results.add(new RennenRennlaeuferDTO(r,
					mannschaftToString(r.getRennlaeufer())));
		}
		return results;
	}
	/**
	 * Ends a trip .
	 * @param id
	 */
	public void beende(int id) {
		HibernateTemplate template = getHibernateTemplate();
		Rennen f = (Rennen) template.get(Rennen.class, id);
		//f.setAnkunft(new Date());
		template.saveOrUpdate(f);
	}
	
	/**
	 * Private utility function
	 * @param rennlaeuferSet a Set of Person objects
	 * @return a String of the names of those Person objects
	 */
	private String mannschaftToString(Set<Rennlaeufer> rennlaeuferSet) {
		if(rennlaeuferSet == null) {
			return "keine Rennläufer";
		}
		//return rennlaeuferSet.size()+"";
		String mannschaft = "";
		String trenner = "";
		for (Rennlaeufer rennlaeufer : rennlaeuferSet) {
			mannschaft = mannschaft + trenner + rennlaeufer.getVorname() + " "
					+ rennlaeufer.getNachname();
			trenner = ", ";
		}
		return mannschaft;
	}

	public void modify(int id, String ort, String datum, String bez, int saison) {
		HibernateTemplate template = getHibernateTemplate();
		Rennen rennen = (Rennen) template.get(Rennen.class, id);
		rennen.setRennort(ort);
		rennen.setRennbezeichnung(bez);
	//	rennen.setBusplatz(platz);
//		SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
	//	try {
	//		rennen.setRenndatum(sdf.parse(datum));
	//	} catch (ParseException e) {
		//	// TODO Auto-generated catch block
	//		e.printStackTrace();  //=> Handling eintragen
	//	}
		
		template.saveOrUpdate(rennen);
		
	}


	public void create(String datum, String ort, String bez, int saisonid) {
		HibernateTemplate template = getHibernateTemplate();
		Rennen rennen = new Rennen(datum, ort, bez, saisonDao.findById(saisonid)); 
		template.persist(rennen);
	}
	
	/**
	 * returns the list of rennen .
	 * @return a List of Rennen
	 */
//	@SuppressWarnings("unchecked")
//	public List<Boot> findFreie() {
//		HibernateTemplate template = getHibernateTemplate();
//		List<Fahrt> aktuelleRennen = template.find("from Fahrt f where f.ankunft is null");
//		List<Rennen> alle = template.loadAll(Rennen.class);
//		List<Rennen> result = new LinkedList<Rennen>();
//		List<Rennen> belegteBoote = new LinkedList<Rennen>();
//		for (Fahrt fahrt : aktuelleRennen) {
//			belegteRennen.add(fahrt.getRennen());
//		}
//		for (Boot boot : alle) {
//			if (!belegteBoote.contains(boot)) {
//				result.add(boot);
//			}
//		}
//		return result;
//	}

	public void deleteById(int id) throws BootDeleteException {
		HibernateTemplate template = getHibernateTemplate();
		Rennen b = findById(id);
//		Set<Rennen> rennen = b;
//		if (rennen == null || rennen.size() == 0) {
			template.delete(b);
//		} else {
//			throw new BootDeleteException();
//		}
	}

	public void konfiguriere(int id, String[] rennlaeuferIds) {
		Rennen rennen = findById(id);
		for (String riString : rennlaeuferIds) {
			int ri = Integer.parseInt(riString);
			this.rennstatistikDao.create(rennen, rennlaeuferDao.findById(ri));
		}
	}

	public void konfiguriereRennstat(int id, String[] rennlaeuferIds, String[] rennlaeuferImBusIds) {
		int[] rennlaeuferImBusIdsInt = new int[rennlaeuferImBusIds.length];
		for (int i = 0; i < rennlaeuferImBusIds.length; i++) {
			rennlaeuferImBusIdsInt[i] = Integer.parseInt(rennlaeuferImBusIds[i]);
		}
		Rennen rennen = findById(id);
		for (String riString : rennlaeuferIds) {
			int ri = Integer.parseInt(riString);
			int rennlaeuferInBusArray = Arrays.binarySearch(rennlaeuferImBusIdsInt, ri);
			this.rennstatistikDao.createRennstat(
					rennen,
					rennlaeuferDao.findById(ri),
					rennlaeuferInBusArray > -1);  //vergleicht das Integer Array mit den Laeufer Array
		}
	}

	//public void modify(int id, String renndatum, String rennort,
	//		String bezeichnung, String saison) {
		// TODO Auto-generated method stub
		
	}
